package com.woniu.adapter;

import com.woniu.inlet.web.vo.FundHoldVo;
import com.woniu.outlet.mysql.dao.HoldProductDao;
import com.woniu.outlet.mysql.po.*;
import com.woniu.service.domain.IncomeDetailsDto;
import com.woniu.service.domain.TransactionDetailsDto;
import com.woniu.utils.NumberRegexValidationUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * 用户持有产品适配类（去重，统领这个产品的作用）
 */
@Component
@Slf4j
@Transactional
public class HoldProductAdapter {

    @Autowired
    private HoldProductDao dao;

    @Autowired
    private PersonalIncomeAdapter personalIncomeAdapter;

    @Autowired
    private DailyIncomeAdapter dailyIncomeAdapter;

    @Autowired
    private ProductBuyAdapter buyAdapter;

    @Autowired
    private ProductSellAdapter sellAdapter;

    /**
     * 新增方法（外用）
     * @param buy
     */
    public void addHoldProduct(ProductBuyMySQL buy){
        //先查询有没有
        List<HoldProductMySQL> hold = findHold(buy);
        if(hold.size()==0){
            //没有就插入
            insert(buy);
            log.debug("HoldProduct表插入新数据");
        }else{
            //有就修改
            HoldProductMySQL mySQL = hold.get(0);
            BigDecimal totalPrincipal = new BigDecimal(buy.getBuyAmount()).subtract(new BigDecimal(buy.getBuyCost()));
            log.debug("原本金额{}，本次买入的金额为{}",mySQL.getTotalPrincipal(),totalPrincipal);
            mySQL.setTotalPrincipal(mySQL.getTotalPrincipal().add(totalPrincipal));
            mySQL.setTotalShare(mySQL.getTotalShare().add(new BigDecimal(buy.getBuyShare().toString())));
            log.debug("追加后的金额为{}，份额为{}",mySQL.getTotalPrincipal(),mySQL.getTotalShare());
            additionalNumber(mySQL);
            log.debug("HoldProduct表更新数据");
        }
    }

    /**
     * 产品卖出时减少本金和份额（外用）
     */
    public void subtractHold(){

    }

    /**
     * 得到当前用户的所有统领的产品信息
     * @return
     */
    public List<HoldProductMySQL> findUserByType(Long userId,String productType){
        HoldProductMySQLExample example=new HoldProductMySQLExample();
        HoldProductMySQLExample.Criteria criteria = example.createCriteria();
        criteria.andProductTypeEqualTo(productType);
        criteria.andUserIdEqualTo(userId);
        return dao.selectByExample(example);

    }

    /**
     * 添加数据
     * @param buyMySQL
     */
    public void insert(ProductBuyMySQL buy){
        BigDecimal totalPrincipal = new BigDecimal(buy.getBuyAmount()).subtract(new BigDecimal(buy.getBuyCost()));
        HoldProductMySQL mySQL=HoldProductMySQL.builder()
                .userId(buy.getUserId())
                .codeId(buy.getCodeId())
                .productType(buy.getProductType())
                .totalPrincipal(totalPrincipal)
                .totalShare(new BigDecimal(buy.getBuyShare().toString()))
                .status(0)
                .build();
        dao.insert(mySQL);
    }

    /**
     * 查询当前用户买的产品是否存在
     * @param buy
     * @return
     */
    public List<HoldProductMySQL> findHold(ProductBuyMySQL buy){
        HoldProductMySQLExample example=new HoldProductMySQLExample();
        HoldProductMySQLExample.Criteria criteria = example.createCriteria();
        criteria.andUserIdEqualTo(buy.getUserId());
        criteria.andCodeIdEqualTo(buy.getCodeId());
        criteria.andProductTypeEqualTo(buy.getProductType());
        return dao.selectByExample(example);
    }

    /**
     * 产品存在就追加本金和份额
     * @param hold
     */
    public void additionalNumber(HoldProductMySQL hold){
        dao.updateByPrimaryKey(hold);
    }


    /**
     * 根据userId和codeId，查询用户当前基金的持仓详情
     * @param userId
     * @param codeId
     */
    public Object fundHoldDetails(Long userId, String codeId) {
        if(!NumberRegexValidationUtil.isPositiveInteger(userId+"")){
            return "invalid";
        }
        //得到当前基金的信息
        HoldProductMySQL fund = getFundOrGold(userId, codeId);
        if(fund.getTotalPrincipal().toString().equals("0")){
            return "0";
        }
        //总收益
        BigDecimal totalIncome = personalIncomeAdapter.getTotalIncome(userId, codeId);
        //昨日收益
        BigDecimal yesterdayIncome = dailyIncomeAdapter.getYesterdayIncome(userId, codeId);
        //收益明细
        List<IncomeDetailsDto> incomeDeteils = getIncomeDeteils(userId, codeId);
        //交易明细
        List<TransactionDetailsDto> transactionDetails = getTransactionDetails(userId, codeId);
        return FundHoldVo.builder()
                .totalMoney(fund.getTotalPrincipal().add(totalIncome))
                .totalShare(fund.getTotalShare())
                .totalIncome(totalIncome)
                .YesterdayIncome(yesterdayIncome)
                .incomeDetails(incomeDeteils)
                .transactionDetails(transactionDetails)
                .build();
    }

    /**
     * 得到交易明细
     */
    public List<TransactionDetailsDto> getTransactionDetails(Long userId, String codeId){
        List<TransactionDetailsDto> transactionDetailsDtos=new ArrayList<>();
        //得到buy
        List<ProductBuyMySQL> buyDeteils = buyAdapter.getBuyDetails(userId, codeId);
        //得到sell
        List<ProductSellMySQL> sellDetalis = sellAdapter.getSellDetalis(userId, codeId);
        if(buyDeteils.size()==0 && sellDetalis.size()==0){
            TransactionDetailsDto dto=TransactionDetailsDto.builder()
                    .type("no")
                    .orderId(0l)
                    .transactionAmount("0")
                    .cost("0")
                    .share("0")
                    .time("0")
                    .build();
            transactionDetailsDtos.add(dto);
            return transactionDetailsDtos;
        }
        if(buyDeteils.size()>0){
            for (ProductBuyMySQL b : buyDeteils) {
                TransactionDetailsDto dto=TransactionDetailsDto.builder()
                        .type("buy")
                        .orderId(b.getId())
                        .transactionAmount(b.getBuyAmount().toString())
                        .cost(b.getBuyCost())
                        .share(b.getBuyShare().toString())
                        .time(b.getBuyTime())
                        .build();
                transactionDetailsDtos.add(dto);
            }
        }
        if(sellDetalis.size()>0){
            for (ProductSellMySQL s : sellDetalis) {
                TransactionDetailsDto dto=TransactionDetailsDto.builder()
                        .type("sell")
                        .orderId(s.getId())
                        .transactionAmount(s.getSellAmount().toString())
                        .cost(s.getSellCost().toString())
                        .share(s.getSellShare())
                        .time(s.getSellTime())
                        .build();
                transactionDetailsDtos.add(dto);
            }
        }
        //根据时间排序
        Collections.sort(transactionDetailsDtos,new SortClass());
        return transactionDetailsDtos;
    }

    /**
     * 卖出后，修改份额
     * @param fund
     * @param bigDecimal
     */
    public void sellFund(HoldProductMySQL fund, BigDecimal sellShare) {
        fund.setTotalShare(fund.getTotalShare().subtract(sellShare));
        dao.updateByPrimaryKey(fund);
    }

    /**
     * 卖出撤销订单还原份额
     * @param userId
     * @param codeId
     * @param revocationShares
     */
    public void sellRevocationShares(Long userId, String codeId, String[] revocationShares) {
        //要撤销的总份额
        BigDecimal allShare=new BigDecimal("0");
        for (String revocationShare : revocationShares) {
            BigDecimal share=new BigDecimal(revocationShare);
            allShare=allShare.add(share);
        }
        log.debug("要撤销的总份额={}",allShare);
        HoldProductMySQLExample example=new HoldProductMySQLExample();
        HoldProductMySQLExample.Criteria criteria = example.createCriteria();
        criteria.andUserIdEqualTo(userId);
        criteria.andCodeIdEqualTo(codeId);
        List<HoldProductMySQL> holdProductMySQLS = dao.selectByExample(example);
        HoldProductMySQL mySQL = holdProductMySQLS.get(0);
        mySQL.setTotalShare(mySQL.getTotalShare().add(allShare));
        dao.updateByPrimaryKey(mySQL);
    }

    /**
     * 删除总的持有份额为0的单子
     * @param userId
     * @param codeId
     */
    public void delOrder(Long userId, String codeId) {
        HoldProductMySQLExample example=new HoldProductMySQLExample();
        HoldProductMySQLExample.Criteria criteria = example.createCriteria();
        criteria.andUserIdEqualTo(userId);
        criteria.andCodeIdEqualTo(codeId);
        List<HoldProductMySQL> holdProductMySQLS = dao.selectByExample(example);
        if(holdProductMySQLS.size()>0){
            HoldProductMySQL mySQL = holdProductMySQLS.get(0);
            if(mySQL.getTotalShare().compareTo(new BigDecimal("0"))==0){
                dao.deleteByPrimaryKey(mySQL.getId());
                log.debug("总的持有份额单子删除成功");
            }
        }else {
            log.debug("找不到userId={},codeId={}，的单子信息",userId,codeId);
        }

    }


    static class SortClass implements Comparator {
        public int compare(Object arg0,Object arg1){
            TransactionDetailsDto dto1 = (TransactionDetailsDto)arg0;
            TransactionDetailsDto dto2 = (TransactionDetailsDto)arg1;
            int flag = dto2.getTime().compareTo(dto1.getTime());
            return flag;
        }
    }


    /**
     * 得到每日收益
     * @param userId
     * @param codeId
     * @return
     */
    public List<IncomeDetailsDto> getIncomeDeteils(Long userId, String codeId){
        List<IncomeDetailsDto> IncomeDetails=new ArrayList<>();
        List<DailyIncomeMySQL> ds = dailyIncomeAdapter.getDailyIncome(userId, codeId);
        for (DailyIncomeMySQL d : ds) {
            IncomeDetailsDto dto=IncomeDetailsDto.builder()
                    .date(d.getTodayDate())
                    .income(d.getTodayIncome())
                    .build();
            IncomeDetails.add(dto);
        }
        return IncomeDetails;
    }

    /**
     * 得到当前基金的信息
     * @param userId
     * @param codeId
     */
    public HoldProductMySQL getFundOrGold(Long userId, String codeId) {
        HoldProductMySQLExample example=new HoldProductMySQLExample();
        HoldProductMySQLExample.Criteria criteria = example.createCriteria();
        criteria.andUserIdEqualTo(userId);
        criteria.andCodeIdEqualTo(codeId);
        List<HoldProductMySQL> holdProductMySQLS = dao.selectByExample(example);
        if(holdProductMySQLS.size()==0){
            return HoldProductMySQL.builder()
                    .totalPrincipal(new BigDecimal("0"))
                    .totalShare(new BigDecimal("0"))
                    .build();
        }
        return holdProductMySQLS.get(0);
    }

    public List<HoldProductMySQL> findAll() {
         return dao.selectByExample(null);
    }
}
